package fr.machizaud.research;

import fr.machizaud.research.handlers.Attribute2Markup;
import fr.machizaud.research.handlers.FCPSequenceMerger;
import fr.machizaud.research.handlers.FCPXMLChecker;
import fr.machizaud.research.handlers.UnusedMarkupCleaner;
import org.jdom.Document;
import org.jdom.JDOMException;
import org.jdom.input.SAXBuilder;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

/**
 * User: Andréa
 * Date: 23/01/11
 * Time: 16:32
 */
public class FCPGenerator
        implements XMLHandler {
    private static final java.util.logging.Logger logger = java.util.logging.Logger.getLogger(FCPGenerator.class.getCanonicalName());

    private static final List<XMLHandler> handlerChain = new ArrayList<XMLHandler>();

    public static String XSD_PATH = null;

    public FCPGenerator(XMLHandler... handlers) {
        for (XMLHandler handler : handlers)
            handlerChain.add(handler);
    }

    @Override
    public void process(Document dom) throws MalformedDocumentException {
        for (XMLHandler handler : handlerChain)
            handler.process(dom);
    }

    public static void main(String[] args) throws ApplicationException {
        try {
            LogManager.getLogManager().readConfiguration(
                    FCPGenerator.class.getClassLoader().getResourceAsStream("logging.properties"));
        } catch (Exception e) {
            logger.log(
                    Level.WARNING, "Unable to read logging configuration file",
                    e);
        }

        boolean sourceRequirementOK = false;
        boolean xsdRequirementOK = false;
        String source = null;
        String output = null;

        //fetching parameters
        for (String arg : args) {
            if (arg.equals("-q")
                    || arg.equals("--quiet")) {
                Logger.getLogger("fr.machizaud.research").setLevel(Level.OFF);
            } else if (arg.equals("-v")
                    || arg.equals("--verbose")) {
                Logger.getLogger("fr.machizaud.research").setLevel(Level.ALL);
            } else if (arg.matches(".*\\.xmi")) {
                source = arg;
                sourceRequirementOK = true;
            } else if (arg.matches(".*\\.xml")) {
                output = arg;
            } else if (arg.matches(".*\\.xsd")) {
                XSD_PATH = arg;
                xsdRequirementOK = true;
            }
        }

        //verifying requirements
        if (!sourceRequirementOK)
            throw new ApplicationException("Please give a   xmi file to refine");
        if (!xsdRequirementOK)
            throw new ApplicationException("Please give the fcp xsd file to proceed");

        logger.info("All requirements met.");

        XMLHandler fcpGenerator = new FCPGenerator(
                UnusedMarkupCleaner.getInstance(),
                Attribute2Markup.getInstance(),
                FCPSequenceMerger.getInstance(),
                FCPXMLChecker.getInstance()
        );
        logger.info("Filter chain built.");

        try {
            logger.info("Building DOM from given file...");
            Document dom = new SAXBuilder().build(
                    new FileInputStream(source)
            );

            logger.info("Start filtering process.");
            fcpGenerator.process(dom);

            String niceMessage = "Writing refined result to ";
            Writer writer = null;
            if (output != null) {
                logger.info(niceMessage + output + ".");
                writer = new FileWriter(output);
            } else {
                logger.info(niceMessage + " standard output.");
                writer = new OutputStreamWriter(System.out);
            }
            XMLOutputter extractor = new XMLOutputter(Format.getPrettyFormat());
            extractor.output(dom, writer);

            logger.info("Process finished.");

            writer.flush();
            writer.close();
            writer = null;

            extractor = null;

            return;
        } catch (JDOMException e) {
            logger.log(Level.SEVERE, "JDOMException", e);
        } catch (IOException e) {
            logger.log(Level.SEVERE, "IOException", e);
        } catch (MalformedDocumentException e) {
            logger.log(Level.SEVERE, "MalformedDocumentException", e);
        }

        logger.severe("Process has encountered some errors, please read logs");
    }

}
